// i.r(t), i.d(t, { default: () => ShowcaseSettings })
import DataSyncStore from "../storage/DataSyncStore"
import Module from "./Module"
import SettingsModule from "./SettingsModule"
import SettingsData from "../data/SettingsData"
import PlayerOptionsData from "../data/PlayerOptionsData"
import playerConst from "../constant/player.const"
import transitionTypeEnum from "../enum/transitionType.enum"
import Logger from "../utils/Logger"
import Store from "../storage/Store"
import { ObjectSync } from "../storage/DataSync"

const deserialize = e => {
  if (!e?.player_options) return null
  const t = e.player_options || {}
  const i = {
    address: t.address,
    background_color: t.background_color,
    contact_email: t.contact_email,
    contact_name: t.contact_name,
    contact_phone: t.contact_phone,
    dollhouse: t.dollhouse,
    dollhouse_pan_speed: t.dollhouse_pan_speed,
    external_url: t.external_url,
    fast_transitions: t.fast_transitions,
    floor_plan: t.floor_plan,
    floor_select: t.floor_select,
    highlight_reel: t.highlight_reel,
    labels: t.labels,
    labels_dh: t.labels_dh,
    measurements: t.measurements,
    measurements_saved: t.measurements_saved,
    model_name: t.model_name,
    model_summary: t.model_summary,
    pan_angle: t.pan_angle,
    pan_direction: t.pan_direction,
    pan_speed: t.pan_speed,
    presented_by: t.presented_by,
    tour_buttons: t.tour_buttons,
    transition_speed: t.transition_speed,
    transition_time: t.transition_time,
    unit_type: t.unit_type || e.unit_type,
    zoom_duration: t.zoom_duration
  }
  return new PlayerOptionsData(i)
}

import Monitor from "../collection/Monitor"
import aggregationTypeEnum from "../enum/aggregationType.enum"
import { SaveCommand } from "../command/data.command"
import optionsKeyEnum from "../enum/optionsKey.enum"
import storageTypeEnum from "../enum/storageType.enum"
import dataTypeEnum from "../enum/dataType.enum"

const F = new Logger("showcase-settings")
export default class ShowcaseSettings extends Module {
  updateTransitionType: any
  engine: any
  store: DataSyncStore
  playerOptionsData: PlayerOptionsData
  monitor: Monitor
  constructor() {
    super(...arguments)
    this.name = "showcase-settings"
    this.updateTransitionType = (e, t, i) => {
      const n = e.options.fast_transitions ? transitionTypeEnum.FadeToBlack : transitionTypeEnum.Interpolate
      t.hasProperty(playerConst.TransitionType) ? t.setProperty(playerConst.TransitionType, n) : i.registerSetting(playerConst.TransitionType, n)
    }
  }
  async init(e, t) {
    this.engine = t
    this.store = this.configureStorage(e)
    const [i, n, l] = await Promise.all([t.getModule(SettingsModule), t.market.waitForData(SettingsData), this.store.read()])
    this.playerOptionsData = l || new PlayerOptionsData()
    t.market.register(this, PlayerOptionsData, this.playerOptionsData)
    this.configureMonitor(e)
    for (const e in optionsKeyEnum) {
      const t = optionsKeyEnum[e],
        n = this.playerOptionsData.options[t]
      if (i.hasProperty(t)) {
        const e = i.getProperty(t)
        i.updateSetting(t, n && e), F.debug(`Updated player_options setting ${t} = ${n && e}`)
      } else i.registerSetting(t, n), F.debug(`Registered player_options setting ${t} = ${n}`)
    }
    this.updateTransitionType(this.playerOptionsData, n, i),
      this.bindings.push(n.onPropertyChanged(optionsKeyEnum.InstantTransitions, () => this.updateTransitionType(this.playerOptionsData, n, i)))
  }
  configureStorage(e) {
    const { modelId, baseUrl, queue } = e
    const r = e.storageProvider || storageTypeEnum.JSONSTORE
    F.info(`Loading player options from ${r}`)
    const path = `${baseUrl}/scene-portal/api/v1/player/models/${modelId}`
    const store = new Store.ReadOnlyStore({
      queue,
      path,
      deserialize,
      cachedData: { data: null }
    })
    const sync = new ObjectSync({ publishStores: [store] })
    return new DataSyncStore(sync, {
      dataType: dataTypeEnum.SETTINGS,
      engine: this.engine
    })
  }
  configureMonitor(e) {
    e.readonly ||
      ((this.monitor = new Monitor(this.playerOptionsData, { aggregationType: aggregationTypeEnum.NextFrame }, this.engine)),
      this.monitor.onChanged(() => this.engine.commandBinder.issueCommand(new SaveCommand({ dataTypes: [dataTypeEnum.SETTINGS] }))),
      this.store instanceof DataSyncStore && this.store.addMonitor(this.monitor))
  }
  async revert() {
    if (this.store instanceof DataSyncStore) return this.store.revert()
  }
}
